package com.ruoyi.common.distributeLock.callback;

import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.common.distributeLock.context.ZkContext;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.MapUtils;
import org.apache.zookeeper.AsyncCallback;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.data.Stat;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.concurrent.CountDownLatch;

/**
 * @author gim 2023/4/19 9:49
 */
@Component
@Slf4j
@RequiredArgsConstructor
@Data
public class ZkCallback implements AsyncCallback.StringCallback, AsyncCallback.StatCallback,AsyncCallback.ChildrenCallback{
    private String pathName;
    private final ZooKeeper zooKeeper;
    private String threadName;
    private final CountDownLatch cou;
    private final Watcher watch;
    @Override
    public void processResult(int rc, String s, Object o, List<String> children) {
        ZkContext context=(ZkContext)o;

        threadName=Thread.currentThread().getName();
        log.info("processResult:"+threadName);
        try{
            if(Objects.isNull(children)){
                return;
            }
            Collections.sort(children);
//            Map<String,String> pathMap=((ZkContext)o).getPathMap();
//            String pathName=pathMap.get(Thread.currentThread().getName());
            int i=children.indexOf(((ZkContext)o).getZkPath(threadName).substring(1));
            if(Objects.equals(i,0)){
                log.info("线程{}抢到了锁", threadName);
                cou.countDown();
            }else{
                log.info("线程{}抢锁失败，重新注册监听器", threadName);
                zooKeeper.exists("/ruoyi/"+children.get(i-1),watch,this,o);
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    @Override
    public void processResult(int i, String s, Object o, Stat stat) {

    }

    /**
     *
     * @param rc 状态码
     * @param s create方法的path入参
     * @param o create方法的上下文入参
     * @param s1 创建成功的临时有序节点名称：path+zk自增id。如果不是有序节点，这里就是path
     */
    @Override
    public void processResult(int rc, String path, Object ctx, String name) {
        log.info(">>>>>>>>>>>>>>>>>processResult,rx:{},path:{},ctx:{},name:{}",rc,path,ctx.toString(),name);
        if(StringUtils.isBlank(name)){
            return;
        }
        Map<String,String> pathMap=((ZkContext)ctx).getPathMap();
        if(MapUtils.isEmpty(pathMap)){
            pathMap=new HashMap<>();
        }
//        pathMap.put(Thread.currentThread().getName(),name.replace("/ruoyi",""));
        ((ZkContext)ctx).setZkPath(Thread.currentThread().getName(),name.replace("/ruoyi",""));
        try {
            zooKeeper.getChildren("/ruoyi",false,this,ctx);
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}
